import tkinter as tk
from tkinter import ttk, messagebox, filedialog
import ttkbootstrap as ttk_bs
from ttkbootstrap.constants import *
import threading
import os
from typing import Dict, Any, List
from core.config import ConfigManager
from core.gitee_api import GiteeAPI
from core.git_operations import GitOperations
from gui.components import ProjectSelector, LogTextWidget, ProgressDialog
from gui.repo_manager import RepoManagerWidget
from utils.logger import get_logger
from utils.validators import Validators
from utils.name_translator import name_translator
from utils.readme_generator import readme_generator
from core.gitee_manager import GiteeManager


class MainWindow:
    """主窗口类"""
    
    def __init__(self, config_manager: ConfigManager):
        self.config_manager = config_manager
        self.logger = get_logger("MainWindow")
        
        # 初始化组件
        self.gitee_api = None
        self.gitee_manager = None
        self.git_ops = GitOperations()
        self.processing = False
        
        # 创建主窗口
        self.setup_main_window()
        self.setup_ui()
        self.load_settings()
        
        # 自动尝试连接API
        self.auto_connect_api()
    
    def setup_main_window(self):
        """设置主窗口"""
        # 获取主题
        theme = self.config_manager.get('app.theme', 'superhero')
        
        # 创建主窗口
        self.root = ttk_bs.Window(
            title=self.config_manager.get('app.window_title', 'Gitee仓库批量管理工具'),
            themename=theme,
            size=tuple(map(int, self.config_manager.get('app.window_size', '1000x900').split('x')))
        )
        
        # 设置窗口图标和属性
        self.root.resizable(True, True)
        self.root.minsize(1000, 650) 
        
        # 设置全局字体为等线
        self.setup_fonts()
        
        # 居中显示
        self.center_window()
        
        # 绑定关闭事件
        self.root.protocol("WM_DELETE_WINDOW", self.on_closing)
    
    def setup_fonts(self):
        """设置全局字体为等线"""
        try:
            import tkinter.font as tkFont
            
            # 设置默认字体为等线
            default_font = tkFont.nametofont("TkDefaultFont")
            default_font.configure(family="等线", size=9)
            
            # 设置文本字体
            text_font = tkFont.nametofont("TkTextFont")
            text_font.configure(family="等线", size=9)
            
            # 设置固定字体
            fixed_font = tkFont.nametofont("TkFixedFont")
            fixed_font.configure(family="等线", size=9)
            
            # 设置菜单字体
            menu_font = tkFont.nametofont("TkMenuFont")
            menu_font.configure(family="等线", size=9)
            
            # 设置标题字体
            caption_font = tkFont.nametofont("TkCaptionFont")
            caption_font.configure(family="等线", size=9)
            
            self.logger.info("全局字体已设置为等线")
            
        except Exception as e:
            self.logger.warning(f"设置字体失败: {e}")
    
    def center_window(self):
        """窗口居中"""
        self.root.update_idletasks()
        width = self.root.winfo_width()
        height = self.root.winfo_height()
        x = (self.root.winfo_screenwidth() // 2) - (width // 2)
        y = (self.root.winfo_screenheight() // 2) - (height // 2)
        self.root.geometry(f'{width}x{height}+{x}+{y}')
    
    def setup_ui(self):
        """设置用户界面"""
        # 创建主框架
        main_frame = ttk.Frame(self.root, padding=10)
        main_frame.pack(fill=BOTH, expand=True)
        
        # 创建笔记本组件（选项卡）
        self.notebook = ttk_bs.Notebook(main_frame, bootstyle="info")
        self.notebook.pack(fill=BOTH, expand=True)
        
        # 创建选项卡
        self.create_config_tab()
        self.create_batch_tab()
        self.create_repo_manager_tab()
        self.create_readme_editor_tab()
        
        # 状态栏
        self.create_status_bar()
    
    def create_config_tab(self):
        """创建配置选项卡"""
        config_frame = ttk.Frame(self.notebook)
        self.notebook.add(config_frame, text="配置设置")
        
        # 创建滚动框架
        canvas = tk.Canvas(config_frame, highlightthickness=0, bg='white')
        scrollbar = ttk.Scrollbar(config_frame, orient="vertical", command=canvas.yview)
        scrollable_frame = ttk.Frame(canvas)
        
        # 配置滚动区域
        def configure_scroll_region(event=None):
            canvas.configure(scrollregion=canvas.bbox("all"))
        
        scrollable_frame.bind("<Configure>", configure_scroll_region)
        
        canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
        canvas.configure(yscrollcommand=scrollbar.set)
        
        # 布局
        canvas.pack(side="left", fill="both", expand=True)
        scrollbar.pack(side="right", fill="y")
        
        # 主容器
        main_container = ttk_bs.Frame(scrollable_frame, padding=20)
        main_container.pack(fill=BOTH, expand=True)
        
        # 绑定鼠标滚轮事件
        def _on_mousewheel(event):
            canvas.yview_scroll(int(-1*(event.delta/120)), "units")
        
        def _on_key_press(event):
            if event.keysym == "Up":
                canvas.yview_scroll(-1, "units")
            elif event.keysym == "Down":
                canvas.yview_scroll(1, "units")
        
        # 绑定到canvas而不是全局
        canvas.bind("<MouseWheel>", _on_mousewheel)
        canvas.bind("<KeyPress>", _on_key_press)
        canvas.focus_set()  # 让canvas可以接收键盘事件
        
        # 设置固定高度和最小高度
        config_frame.configure(height=650)
        config_frame.pack_propagate(False)  # 防止子组件改变父组件大小
        
        # Gitee配置组
        gitee_group = ttk_bs.LabelFrame(main_container, text="Gitee配置", padding=15)
        gitee_group.pack(fill=X, pady=(0, 20))
        
        # Access Token
        token_frame = ttk.Frame(gitee_group)
        token_frame.pack(fill=X, pady=5)
        ttk.Label(token_frame, text="Access Token:", width=15).pack(side=LEFT)
        self.token_var = tk.StringVar()
        self.token_entry = ttk.Entry(token_frame, textvariable=self.token_var, show="*", width=50)
        self.token_entry.pack(side=LEFT, padx=5, fill=X, expand=True)
        
        # 测试连接按钮
        self.test_btn = ttk_bs.Button(
            token_frame, 
            text="测试连接", 
            bootstyle=SUCCESS,
            command=self.test_connection
        )
        self.test_btn.pack(side=RIGHT, padx=5)
        
        # API URL
        url_frame = ttk.Frame(gitee_group)
        url_frame.pack(fill=X, pady=5)
        ttk.Label(url_frame, text="API URL:", width=15).pack(side=LEFT)
        self.url_var = tk.StringVar(value="https://gitee.com/api/v5")
        ttk.Entry(url_frame, textvariable=self.url_var, width=50).pack(side=LEFT, padx=5, fill=X, expand=True)
        
        # 默认分支
        branch_frame = ttk.Frame(gitee_group)
        branch_frame.pack(fill=X, pady=5)
        ttk.Label(branch_frame, text="默认分支:", width=15).pack(side=LEFT)
        self.branch_var = tk.StringVar(value="master")
        branch_combo = ttk_bs.Combobox(branch_frame, textvariable=self.branch_var, width=20)
        branch_combo['values'] = ('master', 'main', 'develop')
        branch_combo.pack(side=LEFT, padx=5)
        
        # DeepSeek AI配置组
        ai_group = ttk_bs.LabelFrame(main_container, text="DeepSeek AI配置", padding=15)
        ai_group.pack(fill=X, pady=(0, 20))
        
        # DeepSeek API Key
        deepseek_frame = ttk.Frame(ai_group)
        deepseek_frame.pack(fill=X, pady=5)
        ttk.Label(deepseek_frame, text="API Key:", width=15).pack(side=LEFT)
        self.deepseek_key_var = tk.StringVar()
        ttk.Entry(deepseek_frame, textvariable=self.deepseek_key_var, show="*", width=50).pack(side=LEFT, padx=5, fill=X, expand=True)
        
        # 提示说明
        hint_frame = ttk.Frame(ai_group)
        hint_frame.pack(fill=X, pady=(5, 0))
        ttk.Label(
            hint_frame, 
            text="💡 配置DeepSeek API Key后可使用AI智能生成项目描述，不配置则使用本地智能分析",
            foreground="gray",
            font=("等线", 8)
        ).pack(side=LEFT)
        
        
        # AI超时设置
        timeout_frame = ttk.Frame(ai_group)
        timeout_frame.pack(fill=X, pady=5)
        ttk.Label(timeout_frame, text="API超时(秒):", width=15).pack(side=LEFT)
        self.ai_timeout_var = tk.StringVar(value="120")
        ttk.Entry(timeout_frame, textvariable=self.ai_timeout_var, width=10).pack(side=LEFT, padx=5)
        ttk.Label(timeout_frame, text="(建议120-300秒)", foreground="gray").pack(side=LEFT, padx=5)
        
        # README生成配置组
        readme_group = ttk_bs.LabelFrame(main_container, text="README生成配置", padding=15)
        readme_group.pack(fill=X, pady=(0, 20))
        
        # 默认生成模式
        mode_frame = ttk.Frame(readme_group)
        mode_frame.pack(fill=X, pady=5)
        ttk.Label(mode_frame, text="默认生成模式:", width=15).pack(side=LEFT)
        self.default_readme_mode_var = tk.StringVar(value="AI智能生成")
        mode_combo = ttk_bs.Combobox(mode_frame, textvariable=self.default_readme_mode_var, width=20)
        mode_combo['values'] = ('AI智能生成', '模板生成')
        mode_combo.pack(side=LEFT, padx=5)
        
        # 默认模板类型
        template_frame = ttk.Frame(readme_group)
        template_frame.pack(fill=X, pady=5)
        ttk.Label(template_frame, text="默认模板:", width=15).pack(side=LEFT)
        self.default_template_var = tk.StringVar(value="详细文档")
        template_combo = ttk_bs.Combobox(template_frame, textvariable=self.default_template_var, width=20)
        template_combo['values'] = ('项目说明', '详细文档', '简单介绍', '自定义')
        template_combo.pack(side=LEFT, padx=5)
        
        # 默认更新方式
        update_frame = ttk.Frame(readme_group)
        update_frame.pack(fill=X, pady=5)
        ttk.Label(update_frame, text="默认更新方式:", width=15).pack(side=LEFT)
        self.default_update_mode_var = tk.StringVar(value="api")
        update_combo = ttk_bs.Combobox(update_frame, textvariable=self.default_update_mode_var, width=20)
        update_combo['values'] = ('api', 'clone')
        update_combo.pack(side=LEFT, padx=5)
        ttk.Label(update_frame, text="(api=API直接更新, clone=克隆到本地)", foreground="gray").pack(side=LEFT, padx=5)
        
        # 批量操作配置组
        batch_group = ttk_bs.LabelFrame(main_container, text="批量操作配置", padding=15)
        batch_group.pack(fill=X, pady=(0, 20))
        
        # 仓库名称前缀
        prefix_frame = ttk.Frame(batch_group)
        prefix_frame.pack(fill=X, pady=5)
        ttk.Label(prefix_frame, text="仓库名称前缀:", width=15).pack(side=LEFT)
        self.prefix_var = tk.StringVar()
        ttk.Entry(prefix_frame, textvariable=self.prefix_var, width=30).pack(side=LEFT, padx=5)
        ttk.Label(prefix_frame, text="(例: my-project-)", foreground="gray").pack(side=LEFT, padx=5)
        
        # 仓库描述模板
        desc_frame = ttk.Frame(batch_group)
        desc_frame.pack(fill=X, pady=5)
        ttk.Label(desc_frame, text="描述模板:", width=15).pack(side=LEFT)
        self.desc_var = tk.StringVar(value="通过批量管理工具创建")
        ttk.Entry(desc_frame, textvariable=self.desc_var, width=50).pack(side=LEFT, padx=5, fill=X, expand=True)
        ttk.Label(desc_frame, text="(支持{project_name}变量)", foreground="gray").pack(side=LEFT, padx=5)
        
        # 批量操作并发数
        concurrency_frame = ttk.Frame(batch_group)
        concurrency_frame.pack(fill=X, pady=5)
        ttk.Label(concurrency_frame, text="并发操作数:", width=15).pack(side=LEFT)
        self.batch_concurrency_var = tk.StringVar(value="3")
        ttk.Entry(concurrency_frame, textvariable=self.batch_concurrency_var, width=10).pack(side=LEFT, padx=5)
        ttk.Label(concurrency_frame, text="(建议1-5，避免API限制)", foreground="gray").pack(side=LEFT, padx=5)
        
        # 批量操作间隔
        interval_frame = ttk.Frame(batch_group)
        interval_frame.pack(fill=X, pady=5)
        ttk.Label(interval_frame, text="操作间隔(秒):", width=15).pack(side=LEFT)
        self.batch_interval_var = tk.StringVar(value="1")
        ttk.Entry(interval_frame, textvariable=self.batch_interval_var, width=10).pack(side=LEFT, padx=5)
        ttk.Label(interval_frame, text="(避免API频率限制)", foreground="gray").pack(side=LEFT, padx=5)
        
        # 批量操作超时
        batch_timeout_frame = ttk.Frame(batch_group)
        batch_timeout_frame.pack(fill=X, pady=5)
        ttk.Label(batch_timeout_frame, text="单次操作超时(秒):", width=15).pack(side=LEFT)
        self.batch_timeout_var = tk.StringVar(value="300")
        ttk.Entry(batch_timeout_frame, textvariable=self.batch_timeout_var, width=10).pack(side=LEFT, padx=5)
        ttk.Label(batch_timeout_frame, text="(建议300-600秒)", foreground="gray").pack(side=LEFT, padx=5)
        
        # 仓库默认配置组
        repo_group = ttk_bs.LabelFrame(main_container, text="仓库默认配置", padding=15)
        repo_group.pack(fill=X, pady=(0, 20))
        
        # 仓库可见性
        visibility_frame = ttk.Frame(repo_group)
        visibility_frame.pack(fill=X, pady=2)
        ttk.Label(visibility_frame, text="仓库可见性:", width=15).pack(side=LEFT)
        
        self.visibility_var = tk.StringVar(value="public")
        public_radio = ttk_bs.Radiobutton(
            visibility_frame, 
            text="公开", 
            variable=self.visibility_var,
            value="public",
            bootstyle="success"
        )
        public_radio.pack(side=LEFT, padx=5)
        
        private_radio = ttk_bs.Radiobutton(
            visibility_frame, 
            text="私有", 
            variable=self.visibility_var,
            value="private",
            bootstyle="warning"
        )
        private_radio.pack(side=LEFT, padx=5)
        
        # 保留原有的private_var用于兼容性
        self.private_var = tk.BooleanVar(value=False)
        
        # Issues
        self.issues_var = tk.BooleanVar(value=True)
        ttk_bs.Checkbutton(
            repo_group, 
            text="开启Issues", 
            variable=self.issues_var,
            bootstyle="success-round-toggle"
        ).pack(anchor=W, pady=2)
        
        # Wiki
        self.wiki_var = tk.BooleanVar(value=True)
        ttk_bs.Checkbutton(
            repo_group, 
            text="开启Wiki", 
            variable=self.wiki_var,
            bootstyle="success-round-toggle"
        ).pack(anchor=W, pady=2)
        
        # 自动初始化
        self.auto_init_var = tk.BooleanVar(value=True)
        ttk_bs.Checkbutton(
            repo_group, 
            text="自动初始化仓库(生成README)", 
            variable=self.auto_init_var,
            bootstyle="success-round-toggle"
        ).pack(anchor=W, pady=2)
        
        # README模板选择
        readme_frame = ttk.Frame(repo_group)
        readme_frame.pack(fill=X, pady=2)
        ttk.Label(readme_frame, text="README模板:", width=15).pack(side=LEFT)
        self.readme_template_var = tk.StringVar(value="AI智能生成")
        readme_combo = ttk_bs.Combobox(readme_frame, textvariable=self.readme_template_var, width=20)
        readme_combo['values'] = ('AI智能生成', '项目说明', '详细文档', '简单介绍', '自定义')
        readme_combo.pack(side=LEFT, padx=5)
        
        # 保存按钮
        button_frame = ttk.Frame(main_container)
        button_frame.pack(fill=X, pady=20)
        
        ttk_bs.Button(
            button_frame,
            text="保存配置",
            bootstyle=PRIMARY,
            command=self.save_config,
            width=20
        ).pack(side=LEFT, padx=5)
        
        ttk_bs.Button(
            button_frame,
            text="重置配置",
            bootstyle=SECONDARY,
            command=self.reset_config,
            width=20
        ).pack(side=LEFT, padx=5)
    
    def create_batch_tab(self):
        """创建批量操作选项卡"""
        batch_frame = ttk.Frame(self.notebook)
        self.notebook.add(batch_frame, text="批量操作")
        
        # 主容器
        main_container = ttk.Frame(batch_frame)
        main_container.pack(fill=BOTH, expand=True, padx=15, pady=15)
        
        # 标题部分
        title_frame = ttk.Frame(main_container)
        title_frame.pack(fill=X, pady=(0, 20))
        
        title_label = ttk.Label(title_frame, text="批量项目管理", font=("等线", 16, "bold"))
        title_label.pack(side=LEFT)
        
        # 快捷操作说明
        desc_label = ttk.Label(
            title_frame, 
            text="选择本地项目，批量创建为Gitee仓库", 
            font=("等线", 10),
            foreground="gray"
        )
        desc_label.pack(side=LEFT, padx=(20, 0))
        
        # 使用PanedWindow分割界面
        paned = ttk_bs.PanedWindow(main_container, orient=VERTICAL)
        paned.pack(fill=BOTH, expand=True)
        
        # 上半部分：项目选择
        top_frame = ttk.Frame(paned)
        paned.add(top_frame, weight=3)
        
        # 项目选择器
        self.project_selector = ProjectSelector(top_frame)
        self.project_selector.pack(fill=BOTH, expand=True)
        
        # 设置回调
        self.project_selector.set_callback('on_project_added', self.on_project_added)
        self.project_selector.set_callback('on_project_removed', self.on_project_removed)
        
        # 下半部分：实时日志
        bottom_frame = ttk_bs.LabelFrame(paned, text="处理日志", padding=5)
        paned.add(bottom_frame, weight=2)
        
        self.log_widget = LogTextWidget(bottom_frame)
        self.log_widget.pack(fill=BOTH, expand=True)
        
        # 底部操作区域
        bottom_controls = ttk.Frame(main_container)
        bottom_controls.pack(fill=X, pady=(15, 0))
        
        # 左侧：预览按钮
        left_buttons = ttk.Frame(bottom_controls)
        left_buttons.pack(side=LEFT)
        
        ttk_bs.Button(
            left_buttons,
            text="🔍 预览仓库名称",
            bootstyle=INFO,
            command=self.preview_repo_names,
            width=18
        ).pack(side=LEFT, padx=(0, 20))
        
        # 中间：进度条
        progress_frame = ttk.Frame(bottom_controls)
        progress_frame.pack(side=LEFT, fill=X, expand=True, padx=20)
        
        # 进度条和百分比
        self.progress_var = tk.DoubleVar()
        self.progress_bar = ttk_bs.Progressbar(
            progress_frame,
            variable=self.progress_var,
            bootstyle=INFO,
            length=200
        )
        self.progress_bar.pack(side=LEFT, fill=X, expand=True, padx=(0, 8))
        
        self.progress_percent_var = tk.StringVar(value="0%")
        self.progress_percent_label = ttk.Label(
            progress_frame, 
            textvariable=self.progress_percent_var,
            font=("等线", 9, "bold"),
            width=6
        )
        self.progress_percent_label.pack(side=RIGHT)
        
        # 右侧：主要操作按钮
        right_buttons = ttk.Frame(bottom_controls)
        right_buttons.pack(side=RIGHT)
        
        # 开始按钮
        self.start_btn = ttk_bs.Button(
            right_buttons,
            text="🚀 开始批量处理",
            bootstyle="success-outline",
            command=self.start_batch_process,
            width=20
        )
        self.start_btn.pack(side=LEFT, padx=(0, 8))
        
        # 停止按钮
        self.stop_btn = ttk_bs.Button(
            right_buttons,
            text="⏹️ 停止处理",
            bootstyle=DANGER,
            command=self.stop_batch_process,
            width=15,
            state=DISABLED
        )
        self.stop_btn.pack(side=LEFT, padx=(0, 8))
        
        # 日志控制按钮
        ttk_bs.Button(
            right_buttons,
            text="清空日志",
            bootstyle=WARNING,
            command=self.log_widget.clear_log,
            width=12
        ).pack(side=LEFT, padx=(0, 5))
        
        ttk_bs.Button(
            right_buttons,
            text="保存日志",
            bootstyle=INFO,
            command=self.log_widget.save_log,
            width=12
        ).pack(side=LEFT)
    
    def create_readme_editor_tab(self):
        """创建README生成和修改选项卡"""
        readme_frame = ttk.Frame(self.notebook)
        self.notebook.add(readme_frame, text="README生成和修改")
        
        # 主容器
        main_container = ttk_bs.Frame(readme_frame, padding=20)
        main_container.pack(fill=BOTH, expand=True)
        
        # 创建上下分栏
        main_paned = ttk.PanedWindow(main_container, orient=tk.VERTICAL)
        main_paned.pack(fill=BOTH, expand=True)
        
        # 上半部分 - 控制面板和编辑器
        top_frame = ttk.Frame(main_paned)
        main_paned.add(top_frame, weight=3)
        
        # 下半部分 - 进度条和日志
        bottom_frame = ttk.Frame(main_paned)
        main_paned.add(bottom_frame, weight=1)
        
        # 顶部按钮区域
        top_buttons = ttk.Frame(top_frame)
        top_buttons.pack(fill=X, pady=(0, 15))
        
        # 左侧：标题
        title_label = ttk.Label(top_buttons, text="README生成和修改", font=("等线", 16, "bold"))
        title_label.pack(side=LEFT)
        
        # 右侧：按钮组
        button_group = ttk.Frame(top_buttons)
        button_group.pack(side=RIGHT)
        
        # 选择仓库按钮
        select_btn = ttk_bs.Button(
            button_group,
            text="📁 选择仓库",
            bootstyle=INFO,
            command=self._open_repo_selector,
            width=15
        )
        select_btn.pack(side=LEFT, padx=(0, 8))
        
        # AI生成README按钮
        generate_btn = ttk_bs.Button(
            button_group,
            text="🤖 AI生成README",
            bootstyle=SUCCESS,
            command=self._generate_readme,
            width=15
        )
        generate_btn.pack(side=LEFT, padx=(0, 8))
        
        # 预览按钮
        preview_btn = ttk_bs.Button(
            button_group,
            text="👁️ 预览效果",
            bootstyle=INFO,
            command=self._preview_readme,
            width=15
        )
        preview_btn.pack(side=LEFT, padx=(0, 8))
        
        # 保存到本地按钮
        save_local_btn = ttk_bs.Button(
            button_group,
            text="💾 保存到本地",
            bootstyle=SECONDARY,
            command=self._save_readme_local,
            width=15
        )
        save_local_btn.pack(side=LEFT, padx=(0, 8))
        
        # 更新到仓库按钮
        update_repo_btn = ttk_bs.Button(
            button_group,
            text="🚀 更新到仓库",
            bootstyle=SUCCESS,
            command=self._update_readme_to_repo,
            width=15
        )
        update_repo_btn.pack(side=LEFT, padx=(0, 8))
        
        # 清空编辑器按钮
        clear_btn = ttk_bs.Button(
            button_group,
            text="🗑️ 清空编辑器",
            bootstyle=WARNING,
            command=self._clear_readme_editor,
            width=15
        )
        clear_btn.pack(side=LEFT)
        
        # 在top_frame中创建左右分栏
        top_paned = ttk.PanedWindow(top_frame, orient=tk.HORIZONTAL)
        top_paned.pack(fill=BOTH, expand=True)
        
        # 左侧控制面板
        left_frame = ttk.Frame(top_paned)
        top_paned.add(left_frame, weight=1)
        
        # 右侧编辑器
        right_frame = ttk.Frame(top_paned)
        top_paned.add(right_frame, weight=2)
        
        self._create_readme_control_panel(left_frame)
        self._create_readme_editor(right_frame)
        
    
    def _create_readme_progress_log(self, parent):
        """创建README页面的进度条和日志显示"""
        # 进度条和日志容器
        progress_log_frame = ttk_bs.LabelFrame(parent, text="操作进度和日志", bootstyle=INFO)
        progress_log_frame.pack(fill=BOTH, expand=True, pady=(10, 0))
        
        # 进度条框架
        progress_frame = ttk.Frame(progress_log_frame)
        progress_frame.pack(fill=X, padx=10, pady=5)
        
        # 进度条
        self.readme_progress_var = tk.DoubleVar()
        self.readme_progress_bar = ttk_bs.Progressbar(
            progress_frame,
            variable=self.readme_progress_var,
            maximum=100,
            bootstyle=INFO,
            length=400
        )
        self.readme_progress_bar.pack(side=LEFT, fill=X, expand=True, padx=(0, 10))
        
        # 进度百分比标签
        self.readme_progress_label = ttk.Label(progress_frame, text="0%", font=("等线", 9))
        self.readme_progress_label.pack(side=RIGHT)
        
        # 状态标签
        self.readme_status_var = tk.StringVar(value="就绪")
        self.readme_status_label = ttk.Label(progress_log_frame, textvariable=self.readme_status_var, font=("等线", 9))
        self.readme_status_label.pack(anchor=W, padx=10, pady=(0, 5))
        
        # 日志显示框架
        log_frame = ttk.Frame(progress_log_frame)
        log_frame.pack(fill=BOTH, expand=True, padx=10, pady=(0, 10))
        
        # 日志文本框
        self.readme_log_text = tk.Text(log_frame, height=6, wrap=tk.WORD, font=("等线", 9))
        readme_log_scrollbar = ttk.Scrollbar(log_frame, orient=tk.VERTICAL, command=self.readme_log_text.yview)
        self.readme_log_text.configure(yscrollcommand=readme_log_scrollbar.set)
        
        # 布局
        self.readme_log_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        readme_log_scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 配置日志标签样式
        self.readme_log_text.tag_configure("INFO", foreground="blue")
        self.readme_log_text.tag_configure("SUCCESS", foreground="green")
        self.readme_log_text.tag_configure("WARNING", foreground="orange")
        self.readme_log_text.tag_configure("ERROR", foreground="red")
        self.readme_log_text.tag_configure("DEBUG", foreground="gray")
        
        # 日志操作按钮
        log_btn_frame = ttk.Frame(progress_log_frame)
        log_btn_frame.pack(fill=X, padx=10, pady=(0, 10))
        
        ttk_bs.Button(
            log_btn_frame,
            text="清空日志",
            bootstyle=SECONDARY,
            command=self._clear_readme_log,
            width=10
        ).pack(side=LEFT, padx=(0, 5))
        
        ttk_bs.Button(
            log_btn_frame,
            text="保存日志",
            bootstyle=INFO,
            command=self._save_readme_log,
            width=10
        ).pack(side=LEFT)
    
    def _append_readme_log(self, message: str, level: str = "INFO"):
        """添加README页面日志"""
        import datetime
        timestamp = datetime.datetime.now().strftime("%H:%M:%S")
        log_message = f"[{timestamp}] {message}\n"
        
        self.readme_log_text.insert(tk.END, log_message, level)
        self.readme_log_text.see(tk.END)
        
        # 限制行数（保留最后500行）
        lines = self.readme_log_text.get("1.0", tk.END).split('\n')
        if len(lines) > 500:
            self.readme_log_text.delete("1.0", f"{len(lines)-500}.0")
    
    def _clear_readme_log(self):
        """清空README页面日志"""
        self.readme_log_text.delete("1.0", tk.END)
    
    def _save_readme_log(self):
        """保存README页面日志"""
        from tkinter import filedialog
        import datetime
        
        filename = filedialog.asksaveasfilename(
            title="保存README操作日志",
            defaultextension=".log",
            filetypes=[("日志文件", "*.log"), ("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(self.readme_log_text.get("1.0", tk.END))
                messagebox.showinfo("成功", f"日志已保存到: {filename}")
            except Exception as e:
                messagebox.showerror("错误", f"保存日志失败: {str(e)}")
    
    def _update_readme_progress(self, progress: int, status: str = ""):
        """更新README页面进度"""
        self.readme_progress_var.set(progress)
        self.readme_progress_label.config(text=f"{progress}%")
        if status:
            self.readme_status_var.set(status)
    
    def _create_readme_control_panel(self, parent):
        """创建README控制面板"""
        # 1. 当前仓库信息板块
        self.current_repo_info = ttk_bs.LabelFrame(parent, text="当前仓库信息", bootstyle=WARNING)
        self.current_repo_info.pack(fill=X, pady=(0, 15))
        
        # 仓库选择状态显示
        self.selected_repo_var = tk.StringVar(value="请选择仓库")
        ttk.Label(self.current_repo_info, textvariable=self.selected_repo_var, 
                 font=("等线", 12, "bold"), foreground="blue").pack(anchor=W, padx=10, pady=(10, 5))
        
        self.repo_info_text = tk.Text(self.current_repo_info, height=4, wrap=tk.WORD, font=("等线", 9))
        self.repo_info_text.pack(fill=X, padx=10, pady=(0, 10))
        self.repo_info_text.config(state=tk.DISABLED)  # 默认不可编辑
        
        # 2. 再次修改板块
        modify_group = ttk_bs.LabelFrame(parent, text="再次修改", bootstyle=INFO)
        modify_group.pack(fill=X, pady=(0, 15))
        
        # 修改需求输入
        ttk.Label(modify_group, text="修改需求:", font=("等线", 10, "bold")).pack(anchor=W, padx=10, pady=(10, 5))
        
        self.modify_input = tk.Text(modify_group, height=3, wrap=tk.WORD, font=("等线", 9))
        self.modify_input.pack(fill=X, padx=10, pady=(0, 10))
        
        # 修改按钮
        modify_btn = ttk_bs.Button(
            modify_group,
            text="🤖 AI二次调整",
            bootstyle=SUCCESS,
            command=self._ai_modify_readme,
            width=15
        )
        modify_btn.pack(anchor=W, padx=10, pady=(0, 10))
        
        # 提示信息
        ttk.Label(modify_group, 
                 text="💡 输入具体修改需求，AI将根据您的要求调整README内容",
                 font=("等线", 8), foreground="gray").pack(anchor=W, padx=10, pady=(0, 10))
        
        # 3. 操作进度和日志板块
        self._create_readme_progress_log(parent)
        
        # 初始化当前选择的仓库
        self.current_repo = None
        
        # 初始化配置变量
        self.readme_mode_var = tk.StringVar()
        self.template_type_var = tk.StringVar()
        self.update_mode_var = tk.StringVar()
        
        # 刷新配置显示
        self._refresh_readme_config()
    
    def _refresh_readme_config(self):
        """刷新README配置显示"""
        try:
            # 从配置管理器获取设置
            readme_mode = self.config_manager.get('readme.default_mode', 'AI智能生成')
            template_type = self.config_manager.get('readme.default_template', '详细文档')
            update_mode = self.config_manager.get('readme.default_update_mode', 'api')
            ai_timeout = self.config_manager.get('ai.timeout', '120')
            
            # 更新变量
            self.readme_mode_var.set(readme_mode)
            self.template_type_var.set(template_type)
            self.update_mode_var.set(update_mode)
            
            # 显示配置信息到仓库信息文本框中
            config_text = f"""生成模式: {readme_mode}
模板类型: {template_type}
更新方式: {'API直接更新' if update_mode == 'api' else 'Clone到本地更新'}
AI超时: {ai_timeout}秒"""
            
            if hasattr(self, 'repo_info_text'):
                self.repo_info_text.config(state=tk.NORMAL)
                self.repo_info_text.delete(1.0, tk.END)
                self.repo_info_text.insert(1.0, config_text)
                self.repo_info_text.config(state=tk.DISABLED)
            
        except Exception as e:
            self.logger.error(f"刷新README配置失败: {e}")
    
    def _create_readme_editor(self, parent):
        """创建README编辑器"""
        # 标题
        title_label = ttk.Label(parent, text="README编辑器", font=("等线", 14, "bold"))
        title_label.pack(anchor=W, pady=(0, 10))
        
        # 编辑器框架
        editor_frame = ttk.Frame(parent)
        editor_frame.pack(fill=BOTH, expand=True)
        
        # 创建文本编辑器
        self.readme_editor = tk.Text(editor_frame, wrap=tk.WORD, font=("Consolas", 10))
        
        # 添加滚动条
        editor_scrollbar = ttk.Scrollbar(editor_frame, orient=VERTICAL, command=self.readme_editor.yview)
        self.readme_editor.configure(yscrollcommand=editor_scrollbar.set)
        
        self.readme_editor.pack(side=LEFT, fill=BOTH, expand=True)
        editor_scrollbar.pack(side=RIGHT, fill=Y)
        
        # 编辑器状态标签
        self.editor_status_var = tk.StringVar(value="请选择仓库并生成README")
        status_label = ttk.Label(parent, textvariable=self.editor_status_var, font=("等线", 10))
        status_label.pack(anchor=W, pady=(5, 0))
    
    
    def _on_mode_changed(self, *args):
        """生成模式变化时的处理"""
        mode = self.readme_mode_var.get()
        if mode == "模板生成":
            self.template_frame.pack(fill=X, padx=10, pady=5)
        else:
            self.template_frame.pack_forget()
    
    def _open_repo_selector(self):
        """打开仓库选择器对话框"""
        if not self.gitee_api:
            messagebox.showerror("错误", "请先配置并连接Gitee API")
            return
        
        # 创建仓库选择对话框
        selector_dialog = RepoSelectorDialog(self.root, self.gitee_api)
        self.root.wait_window(selector_dialog.dialog)
        
        # 检查是否选择了仓库
        if selector_dialog.selected_repo:
            self.current_repo = selector_dialog.selected_repo
            self._update_selected_repo_display()
    
    def _update_selected_repo_display(self):
        """更新选中的仓库显示"""
        if self.current_repo and isinstance(self.current_repo, dict):
            repo_name = self.current_repo.get('name', 'Unknown')
            self.selected_repo_var.set(f"已选择: {repo_name}")
            self._update_repo_info_display(self.current_repo)
            self.editor_status_var.set(f"已选择仓库: {repo_name}")
            
            # 尝试加载现有README文件
            self._load_existing_readme()
        else:
            self.selected_repo_var.set("请从仓库管理页面选择仓库")
            self.repo_info_text.delete(1.0, tk.END)
            self.editor_status_var.set("请选择仓库并生成README")
            # 如果current_repo不是字典，重置为None
            if self.current_repo and not isinstance(self.current_repo, dict):
                self.current_repo = None
    
    def _load_existing_readme(self):
        """加载现有README文件到编辑器"""
        if not self.current_repo:
            return
        
        try:
            repo_name = self.current_repo.get('name', '')
            repo_full_name = self.current_repo.get('full_name', '')
            
            if not repo_full_name:
                return
            
            self._append_readme_log(f"正在检查仓库 {repo_name} 的现有README文件...", "INFO")
            
            # 使用Gitee API获取README文件内容
            from core.gitee_api import GiteeAPI
            from core.config import config_manager
            
            access_token = config_manager.get('gitee.access_token', '')
            if not access_token:
                self._append_readme_log("未配置Gitee Access Token，无法获取现有README", "WARNING")
                return
            
            gitee_api = GiteeAPI(access_token)
            
            # 尝试获取README文件
            success, message, readme_content = gitee_api.get_file_content(repo_full_name, "README.md")
            
            if success and readme_content:
                # 解码Base64内容
                import base64
                try:
                    decoded_content = base64.b64decode(readme_content).decode('utf-8')
                    
                    # 清空编辑器并插入现有内容
                    self.readme_editor.delete(1.0, tk.END)
                    self.readme_editor.insert(1.0, decoded_content)
                    
                    self.editor_status_var.set(f"已加载现有README - 仓库: {repo_name}")
                    self._append_readme_log(f"成功加载现有README文件 ({len(decoded_content)} 字符)", "SUCCESS")
                    
                except Exception as e:
                    self._append_readme_log(f"解码README内容失败: {str(e)}", "ERROR")
            else:
                self._append_readme_log(f"仓库 {repo_name} 没有现有README文件", "INFO")
                # 清空编辑器
                self.readme_editor.delete(1.0, tk.END)
                self.editor_status_var.set(f"仓库无现有README - 仓库: {repo_name}")
                
        except Exception as e:
            self._append_readme_log(f"加载现有README时出错: {str(e)}", "ERROR")
    
    def _get_clone_url(self, repo_info):
        """获取仓库克隆地址，优先使用HTTPS地址"""
        # 调试：打印仓库信息的所有字段
        self.logger.info(f"仓库信息字段: {list(repo_info.keys())}")
        
        # 优先尝试HTTPS地址字段
        https_fields = ['clone_url', 'html_url']
        for field in https_fields:
            url = repo_info.get(field, '')
            self.logger.info(f"尝试HTTPS字段 {field}: {url}")
            if url and url.startswith('https://'):
                self.logger.info(f"找到HTTPS克隆地址: {url}")
                return url
        
        # 如果找到SSH地址，转换为HTTPS
        ssh_url = repo_info.get('ssh_url', '')
        if ssh_url and ssh_url.startswith('git@gitee.com:'):
            # 将 git@gitee.com:owner/repo.git 转换为 https://gitee.com/owner/repo.git
            https_url = ssh_url.replace('git@gitee.com:', 'https://gitee.com/')
            self.logger.info(f"将SSH地址转换为HTTPS: {ssh_url} -> {https_url}")
            return https_url
        
        # 如果都没有找到，尝试构建HTTPS URL
        repo_name = repo_info.get('name', '')
        owner = repo_info.get('owner', {}).get('login', '')
        self.logger.info(f"仓库名称: {repo_name}, 所有者: {owner}")
        
        if repo_name and owner:
            constructed_url = f"https://gitee.com/{owner}/{repo_name}.git"
            self.logger.info(f"构建的克隆地址: {constructed_url}")
            return constructed_url
        
        self.logger.warning("无法获取或构建克隆地址")
        return ''
    
    def _update_repo_info_display(self, repo_info):
        """更新仓库信息显示"""
        clone_url = self._get_clone_url(repo_info)
        info_text = f"""仓库名称: {repo_info.get('name', 'N/A')}
描述: {repo_info.get('description', 'N/A')}
类型: {'私有' if repo_info.get('private', False) else '公开'}
创建时间: {repo_info.get('created_at', 'N/A')[:10]}
更新时间: {repo_info.get('updated_at', 'N/A')[:10]}
克隆地址: {clone_url or 'N/A'}
"""
        self.repo_info_text.delete(1.0, tk.END)
        self.repo_info_text.insert(1.0, info_text)
    
    def _generate_readme(self):
        """生成README"""
        if not hasattr(self, 'current_repo') or not self.current_repo:
            messagebox.showwarning("警告", "请先选择一个仓库")
            return
        
        try:
            repo_name = self.current_repo.get('name', '')
            self._update_readme_progress(0, "开始生成README...")
            self._append_readme_log(f"开始为仓库 {repo_name} 生成README...", "INFO")
            
            # 检查更新模式
            update_mode = self.update_mode_var.get()
            
            if update_mode == "api":
                # API直接更新模式
                self._generate_readme_via_api()
            else:
                # Clone到本地更新模式
                self._generate_readme_via_clone()
                    
        except Exception as e:
            self._append_readme_log(f"生成README时出错: {str(e)}", "ERROR")
    
    def _generate_readme_via_api(self):
        """通过API直接生成和更新README"""
        try:
            repo_name = self.current_repo.get('name', '')
            repo_full_name = self.current_repo.get('full_name', '')
            
            if not repo_full_name:
                self._append_readme_log("无法获取仓库完整名称", "ERROR")
                return
            
            self._update_readme_progress(10, "使用API模式生成README...")
            self._append_readme_log("使用API模式生成README（不占用本地空间）...", "INFO")
            
            # 准备项目信息
            project_info = {
                'name': repo_name,
                'description': self.current_repo.get('description', ''),
                'author': '开发者'
            }
            
            # 根据模式生成README
            mode = self.readme_mode_var.get()
            readme_content = None
            
            if mode == "AI智能生成":
                # 对于API模式，调用DeepSeek AI重新生成README内容
                self._update_readme_progress(30, "正在调用DeepSeek AI...")
                self._append_readme_log("正在调用DeepSeek AI重新生成README内容...", "INFO")
                
                # 使用DeepSeek AI重新生成README内容
                from utils.readme_generator import ReadmeGenerator
                readme_gen = ReadmeGenerator()
                
                # 调用AI生成README（这会真正调用DeepSeek API）
                readme_content = readme_gen.generate_ai_readme(repo_full_name, project_info)
                
                if readme_content:
                    self._update_readme_progress(60, "AI生成完成")
                    self._append_readme_log("DeepSeek AI重新生成README内容完成", "SUCCESS")
                else:
                    self._append_readme_log("DeepSeek AI生成失败，尝试本地智能分析", "WARNING")
                    # 如果AI生成失败，使用本地智能分析
                    analysis = readme_gen._analyze_repo_info(repo_full_name, project_info)
                    readme_content = readme_gen._generate_local_ai_readme(project_info, analysis)
                    
                    if readme_content:
                        self._update_readme_progress(60, "本地分析完成")
                        self._append_readme_log("本地智能分析生成README内容完成", "SUCCESS")
                    else:
                        self._append_readme_log("README内容生成失败", "ERROR")
            else:
                # 使用模板重新生成
                template_type = self.template_type_var.get()
                self._update_readme_progress(30, "使用模板生成...")
                self._append_readme_log(f"正在使用{template_type}模板重新生成README...", "INFO")
                
                from utils.readme_generator import ReadmeGenerator
                readme_gen = ReadmeGenerator()
                readme_content = readme_gen.generate_readme_content(template_type, project_info)
                
                if readme_content:
                    self.log_widget.append_log(f"{template_type}模板生成README内容完成", "SUCCESS")
                else:
                    self.log_widget.append_log(f"{template_type}模板生成README内容失败", "ERROR")
            
            if readme_content:
                # 显示在编辑器中
                self.readme_editor.delete(1.0, tk.END)
                self.readme_editor.insert(1.0, readme_content)
                self.editor_status_var.set(f"README已生成 - 仓库: {repo_name}")
                self.log_widget.append_log("README生成完成，可以手动修改后直接更新到仓库", "SUCCESS")
            else:
                self.log_widget.append_log("README生成失败", "ERROR")
                
        except Exception as e:
            self.log_widget.append_log(f"API模式生成README失败: {str(e)}", "ERROR")
    
    def _generate_readme_via_clone(self):
        """通过克隆仓库生成README"""
        try:
            repo_name = self.current_repo.get('name', '')
            
            # 创建临时目录来克隆仓库
            import tempfile
            import shutil
            from pathlib import Path
            
            with tempfile.TemporaryDirectory() as temp_dir:
                try:
                    # 克隆仓库到临时目录
                    clone_url = self._get_clone_url(self.current_repo)
                    if not clone_url:
                        messagebox.showerror("错误", "无法获取仓库克隆地址")
                        return
                    
                    self.log_widget.append_log("正在克隆仓库...", "INFO")
                    success, message = self.git_ops.clone_repository(clone_url, temp_dir)
                    
                    if not success:
                        self.log_widget.append_log(f"克隆仓库失败: {message}", "ERROR")
                        return
                    
                    self.log_widget.append_log("仓库克隆成功，开始分析代码...", "SUCCESS")
                    
                    # 准备项目信息
                    project_info = {
                        'name': repo_name,
                        'description': self.current_repo.get('description', ''),
                        'author': '开发者'
                    }
                    
                    # 根据模式生成README
                    mode = self.readme_mode_var.get()
                    if mode == "AI智能生成":
                        readme_content = readme_generator.generate_ai_readme(temp_dir, project_info)
                        if not readme_content:
                            self.log_widget.append_log("AI生成失败，使用本地智能分析", "WARNING")
                            from core.deepseek_ai import deepseek_ai
                            analysis = deepseek_ai.analyze_project_files(temp_dir)
                            readme_content = readme_generator._generate_local_ai_readme(project_info, analysis)
                    else:
                        template_type = self.template_type_var.get()
                        readme_content = readme_generator.generate_readme_content(template_type, project_info)
                    
                    if readme_content:
                        # 显示在编辑器中
                        self.readme_editor.delete(1.0, tk.END)
                        self.readme_editor.insert(1.0, readme_content)
                        self.editor_status_var.set(f"README已生成 - 仓库: {repo_name}")
                        self.log_widget.append_log("README生成完成", "SUCCESS")
                    else:
                        self.log_widget.append_log("README生成失败", "ERROR")
                        
                finally:
                    # 确保临时目录被清理
                    self.log_widget.append_log("正在清理临时文件...", "INFO")
                    try:
                        import shutil
                        shutil.rmtree(temp_dir, ignore_errors=True)
                        self.log_widget.append_log("临时文件清理完成", "SUCCESS")
                    except Exception as e:
                        self.log_widget.append_log(f"清理临时文件失败: {str(e)}", "WARNING")
                    
        except Exception as e:
            self.log_widget.append_log(f"克隆模式生成README失败: {str(e)}", "ERROR")
    
    def _preview_readme(self):
        """预览README效果"""
        content = self.readme_editor.get(1.0, tk.END).strip()
        if not content:
            messagebox.showwarning("警告", "编辑器中没有内容")
            return
        
        try:
            # 创建Markdown预览窗口
            preview_window = ttk_bs.Toplevel(self.root)
            preview_window.title("README预览 - Markdown渲染")
            preview_window.geometry("1000x700")
            
            # 创建主框架
            main_frame = ttk.Frame(preview_window)
            main_frame.pack(fill=BOTH, expand=True, padx=10, pady=10)
            
            # 创建应用内HTML预览
            self._create_internal_html_preview(main_frame, content)
            
        except Exception as e:
            # 如果HTML预览失败，回退到文本预览
            self._fallback_text_preview(content)
    
    def _create_internal_html_preview(self, parent, content):
        """创建应用内HTML预览"""
        try:
            import markdown
            
            # 转换Markdown为HTML
            html_content = markdown.markdown(
                content, 
                extensions=[
                    'markdown.extensions.tables',
                    'markdown.extensions.fenced_code',
                    'markdown.extensions.codehilite',
                    'markdown.extensions.toc',
                    'markdown.extensions.extra'
                ]
            )
            
            # 创建完整的HTML内容
            full_html = f"""
            <!DOCTYPE html>
            <html>
            <head>
                <meta charset="UTF-8">
                <style>
                    body {{
                        font-family: 'Microsoft YaHei', '等线', Arial, sans-serif;
                        line-height: 1.6;
                        margin: 0;
                        padding: 20px;
                        background-color: #f8f9fa;
                    }}
                    .container {{
                        background: white;
                        padding: 30px;
                        border-radius: 8px;
                        box-shadow: 0 2px 10px rgba(0,0,0,0.1);
                        max-width: 100%;
                    }}
                    h1, h2, h3, h4, h5, h6 {{
                        color: #2c3e50;
                        border-bottom: 2px solid #3498db;
                        padding-bottom: 10px;
                    }}
                    code {{
                        background-color: #f4f4f4;
                        padding: 2px 4px;
                        border-radius: 3px;
                        font-family: 'Consolas', 'Monaco', monospace;
                    }}
                    pre {{
                        background-color: #2d3748;
                        color: #e2e8f0;
                        padding: 15px;
                        border-radius: 5px;
                        overflow-x: auto;
                    }}
                    pre code {{
                        background: none;
                        color: inherit;
                    }}
                    table {{
                        border-collapse: collapse;
                        width: 100%;
                        margin: 20px 0;
                    }}
                    th, td {{
                        border: 1px solid #ddd;
                        padding: 12px;
                        text-align: left;
                    }}
                    th {{
                        background-color: #f2f2f2;
                        font-weight: bold;
                    }}
                    blockquote {{
                        border-left: 4px solid #3498db;
                        margin: 0;
                        padding: 0 20px;
                        color: #666;
                    }}
                    a {{
                        color: #3498db;
                        text-decoration: none;
                    }}
                    a:hover {{
                        text-decoration: underline;
                    }}
                </style>
            </head>
            <body>
                <div class="container">
                    {html_content}
                </div>
            </body>
            </html>
            """
            
            # 使用简化的HTML预览（基于文本组件）
            self._create_simple_html_preview(parent, full_html)
            
        except ImportError:
            # 如果没有markdown库，使用文本预览
            self._fallback_text_preview(content)
        except Exception as e:
            messagebox.showerror("错误", f"预览失败: {str(e)}")
            self._fallback_text_preview(content)
    
    def _create_simple_html_preview(self, parent, html_content):
        """创建简化的HTML预览"""
        try:
            # 创建滚动区域
            canvas = tk.Canvas(parent, bg='white')
            scrollbar = ttk.Scrollbar(parent, orient="vertical", command=canvas.yview)
            scrollable_frame = ttk.Frame(canvas)
            
            scrollable_frame.bind(
                "<Configure>",
                lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
            )
            
            canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
            canvas.configure(yscrollcommand=scrollbar.set)
            
            # 创建文本显示区域
            text_widget = tk.Text(
                scrollable_frame, 
                wrap=tk.WORD, 
                font=("等线", 10),
                bg='white',
                fg='black',
                padx=20,
                pady=20
            )
            text_widget.pack(fill=BOTH, expand=True)
            
            # 解析HTML并格式化显示
            formatted_text = self._parse_html_to_text(html_content)
            
            # 插入格式化后的文本
            text_widget.insert(1.0, formatted_text)
            text_widget.config(state=tk.DISABLED)
            
            # 布局
            canvas.pack(side="left", fill="both", expand=True)
            scrollbar.pack(side="right", fill="y")
            
            # 绑定鼠标滚轮
            def _on_mousewheel(event):
                try:
                    canvas.yview_scroll(int(-1*(event.delta/120)), "units")
                except tk.TclError:
                    # 如果canvas已销毁，忽略错误
                    pass
            
            # 绑定到canvas而不是全局
            canvas.bind("<MouseWheel>", _on_mousewheel)
            
            # 当窗口关闭时解绑事件
            def _on_close():
                try:
                    canvas.unbind("<MouseWheel>")
                except:
                    pass
            
            # 绑定窗口关闭事件
            preview_window.protocol("WM_DELETE_WINDOW", _on_close)
            
        except Exception as e:
            messagebox.showerror("错误", f"创建预览失败: {str(e)}")
            self._fallback_text_preview(html_content)
    
    def _parse_html_to_text(self, html_content):
        """解析HTML为格式化的文本"""
        import re
        
        # 提取body内容
        body_match = re.search(r'<body[^>]*>(.*?)</body>', html_content, re.DOTALL)
        if body_match:
            body_content = body_match.group(1)
        else:
            body_content = html_content
        
        # 提取container内容
        container_match = re.search(r'<div class="container"[^>]*>(.*?)</div>', body_content, re.DOTALL)
        if container_match:
            content = container_match.group(1)
        else:
            content = body_content
        
        # 处理各种HTML标签
        # 标题
        content = re.sub(r'<h1[^>]*>(.*?)</h1>', r'\n\n# \1\n', content, flags=re.DOTALL)
        content = re.sub(r'<h2[^>]*>(.*?)</h2>', r'\n\n## \1\n', content, flags=re.DOTALL)
        content = re.sub(r'<h3[^>]*>(.*?)</h3>', r'\n\n### \1\n', content, flags=re.DOTALL)
        content = re.sub(r'<h4[^>]*>(.*?)</h4>', r'\n\n#### \1\n', content, flags=re.DOTALL)
        content = re.sub(r'<h5[^>]*>(.*?)</h5>', r'\n\n##### \1\n', content, flags=re.DOTALL)
        content = re.sub(r'<h6[^>]*>(.*?)</h6>', r'\n\n###### \1\n', content, flags=re.DOTALL)
        
        # 段落
        content = re.sub(r'<p[^>]*>(.*?)</p>', r'\1\n\n', content, flags=re.DOTALL)
        
        # 代码块
        content = re.sub(r'<pre[^>]*><code[^>]*>(.*?)</code></pre>', r'\n```\n\1\n```\n', content, flags=re.DOTALL)
        content = re.sub(r'<code[^>]*>(.*?)</code>', r'`\1`', content, flags=re.DOTALL)
        
        # 列表
        content = re.sub(r'<ul[^>]*>(.*?)</ul>', r'\1', content, flags=re.DOTALL)
        content = re.sub(r'<ol[^>]*>(.*?)</ol>', r'\1', content, flags=re.DOTALL)
        content = re.sub(r'<li[^>]*>(.*?)</li>', r'• \1\n', content, flags=re.DOTALL)
        
        # 表格
        content = re.sub(r'<table[^>]*>(.*?)</table>', r'\n\1\n', content, flags=re.DOTALL)
        content = re.sub(r'<tr[^>]*>(.*?)</tr>', r'\1\n', content, flags=re.DOTALL)
        content = re.sub(r'<th[^>]*>(.*?)</th>', r'| \1 ', content, flags=re.DOTALL)
        content = re.sub(r'<td[^>]*>(.*?)</td>', r'| \1 ', content, flags=re.DOTALL)
        
        # 引用
        content = re.sub(r'<blockquote[^>]*>(.*?)</blockquote>', r'\n> \1\n', content, flags=re.DOTALL)
        
        # 链接
        content = re.sub(r'<a[^>]*href="([^"]*)"[^>]*>(.*?)</a>', r'[\2](\1)', content, flags=re.DOTALL)
        
        # 粗体和斜体
        content = re.sub(r'<strong[^>]*>(.*?)</strong>', r'**\1**', content, flags=re.DOTALL)
        content = re.sub(r'<b[^>]*>(.*?)</b>', r'**\1**', content, flags=re.DOTALL)
        content = re.sub(r'<em[^>]*>(.*?)</em>', r'*\1*', content, flags=re.DOTALL)
        content = re.sub(r'<i[^>]*>(.*?)</i>', r'*\1*', content, flags=re.DOTALL)
        
        # 移除剩余的HTML标签
        content = re.sub(r'<[^>]+>', '', content)
        
        # 清理多余的空行和空格
        content = re.sub(r'\n\s*\n\s*\n', '\n\n', content)  # 合并多个空行
        content = re.sub(r'[ \t]+', ' ', content)  # 合并多个空格
        content = content.strip()
        
        return content
    
    def _fallback_text_preview(self, content):
        """回退到文本预览"""
        # 创建预览窗口
        preview_window = ttk_bs.Toplevel(self.root)
        preview_window.title("README预览")
        preview_window.geometry("800x600")
        
        # 创建文本显示区域
        text_frame = ttk.Frame(preview_window)
        text_frame.pack(fill=BOTH, expand=True, padx=10, pady=10)
        
        text_widget = tk.Text(text_frame, wrap=tk.WORD, font=("等线", 10))
        scrollbar = ttk.Scrollbar(text_frame, orient=VERTICAL, command=text_widget.yview)
        text_widget.configure(yscrollcommand=scrollbar.set)
        
        text_widget.pack(side=LEFT, fill=BOTH, expand=True)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        # 插入内容
        text_widget.insert(1.0, content)
        text_widget.config(state=tk.DISABLED)
    
    def _save_readme_local(self):
        """保存README到本地"""
        content = self.readme_editor.get(1.0, tk.END).strip()
        if not content:
            messagebox.showwarning("警告", "编辑器中没有内容")
            return
        
        filename = filedialog.asksaveasfilename(
            title="保存README文件",
            defaultextension=".md",
            filetypes=[("Markdown文件", "*.md"), ("文本文件", "*.txt"), ("所有文件", "*.*")]
        )
        
        if filename:
            try:
                with open(filename, 'w', encoding='utf-8') as f:
                    f.write(content)
                messagebox.showinfo("成功", f"README已保存到: {filename}")
                self.log_widget.append_log(f"README已保存到本地: {filename}", "SUCCESS")
            except Exception as e:
                messagebox.showerror("错误", f"保存文件失败: {str(e)}")
                self.log_widget.append_log(f"保存文件失败: {str(e)}", "ERROR")
    
    def _update_readme_to_repo(self):
        """更新README到仓库"""
        if not hasattr(self, 'current_repo') or not self.current_repo:
            messagebox.showwarning("警告", "请先选择一个仓库")
            return
        
        content = self.readme_editor.get(1.0, tk.END).strip()
        if not content:
            messagebox.showwarning("警告", "编辑器中没有内容")
            return
        
        try:
            repo_name = self.current_repo.get('name', '')
            self.log_widget.append_log(f"开始更新仓库 {repo_name} 的README...", "INFO")
            
            # 检查更新模式
            update_mode = self.update_mode_var.get()
            
            if update_mode == "api":
                # API直接更新模式
                self._update_readme_via_api(content)
            else:
                # Clone到本地更新模式
                self._update_readme_via_clone(content)
                    
        except Exception as e:
            self.log_widget.append_log(f"更新README时出错: {str(e)}", "ERROR")
    
    def _update_readme_via_api(self, content):
        """通过API直接更新README"""
        try:
            repo_name = self.current_repo.get('name', '')
            repo_full_name = self.current_repo.get('full_name', '')
            
            if not repo_full_name:
                self.log_widget.append_log("无法获取仓库完整名称", "ERROR")
                return
            
            self.log_widget.append_log("使用API模式更新README（不占用本地空间）...", "INFO")
            
            # 使用Gitee API直接更新文件
            success, message = self.gitee_api.update_file_content(
                repo_full_name, 
                "README.md", 
                content, 
                "更新README文件",
                "master"  # 默认分支
            )
            
            if success:
                self.log_widget.append_log(f"仓库 {repo_name} 的README更新成功", "SUCCESS")
                messagebox.showinfo("成功", f"仓库 {repo_name} 的README已通过API更新")
            else:
                self.log_widget.append_log(f"API更新失败: {message}", "ERROR")
                messagebox.showerror("错误", f"API更新失败: {message}")
                
        except Exception as e:
            self.log_widget.append_log(f"API模式更新README失败: {str(e)}", "ERROR")
    
    def _update_readme_via_clone(self, content):
        """通过克隆仓库更新README"""
        try:
            repo_name = self.current_repo.get('name', '')
            
            # 创建临时目录
            import tempfile
            import shutil
            from pathlib import Path
            
            with tempfile.TemporaryDirectory() as temp_dir:
                try:
                    # 克隆仓库
                    clone_url = self._get_clone_url(self.current_repo)
                    if not clone_url:
                        self.log_widget.append_log("无法获取仓库克隆地址", "ERROR")
                        return
                        
                    success, message = self.git_ops.clone_repository(clone_url, temp_dir)
                    
                    if not success:
                        self.log_widget.append_log(f"克隆仓库失败: {message}", "ERROR")
                        return
                    
                    # 写入README文件
                    readme_path = os.path.join(temp_dir, 'README.md')
                    with open(readme_path, 'w', encoding='utf-8') as f:
                        f.write(content)
                    
                    # 提交并推送更改
                    self.log_widget.append_log("正在提交更改...", "INFO")
                    success, message = self.git_ops.add_and_commit(temp_dir, "更新README文件")
                    
                    if success:
                        success, message = self.git_ops.push_to_remote(temp_dir)
                        if success:
                            self.log_widget.append_log(f"仓库 {repo_name} 的README更新成功", "SUCCESS")
                            messagebox.showinfo("成功", f"仓库 {repo_name} 的README已更新")
                        else:
                            self.log_widget.append_log(f"推送更改失败: {message}", "ERROR")
                    else:
                        self.log_widget.append_log(f"提交更改失败: {message}", "ERROR")
                        
                finally:
                    # 确保临时目录被清理
                    self.log_widget.append_log("正在清理临时文件...", "INFO")
                    try:
                        import shutil
                        shutil.rmtree(temp_dir, ignore_errors=True)
                        self.log_widget.append_log("临时文件清理完成", "SUCCESS")
                    except Exception as e:
                        self.log_widget.append_log(f"清理临时文件失败: {str(e)}", "WARNING")
                    
        except Exception as e:
            self.log_widget.append_log(f"克隆模式更新README失败: {str(e)}", "ERROR")
    
    def _ai_modify_readme(self):
        """AI二次调整README"""
        if not hasattr(self, 'current_repo') or not self.current_repo:
            messagebox.showwarning("警告", "请先选择一个仓库")
            return
        
        modify_requirements = self.modify_input.get(1.0, tk.END).strip()
        if not modify_requirements:
            messagebox.showwarning("警告", "请输入修改需求")
            return
        
        try:
            repo_name = self.current_repo.get('name', '')
            self._update_readme_progress(0, "AI正在分析修改需求...")
            self._append_readme_log(f"开始为仓库 {repo_name} 进行AI二次调整...", "INFO")
            
            # 获取当前README内容
            current_content = self.readme_editor.get(1.0, tk.END).strip()
            if not current_content:
                messagebox.showwarning("警告", "编辑器中没有README内容，请先生成README")
                return
            
            # 调用AI进行二次调整
            from utils.readme_generator import ReadmeGenerator
            readme_gen = ReadmeGenerator()
            
            # 准备项目信息
            project_info = {
                'name': repo_name,
                'description': self.current_repo.get('description', ''),
                'author': '开发者'
            }
            
            # 使用AI调整README内容
            modified_content = readme_gen.ai_modify_readme(
                current_content, 
                modify_requirements, 
                project_info
            )
            
            if modified_content:
                # 更新编辑器内容
                self.readme_editor.delete(1.0, tk.END)
                self.readme_editor.insert(1.0, modified_content)
                self.editor_status_var.set(f"README已AI调整 - 仓库: {repo_name}")
                
                self._update_readme_progress(100, "AI调整完成")
                self._append_readme_log("AI二次调整完成", "SUCCESS")
                messagebox.showinfo("成功", "README内容已根据您的需求进行调整！")
            else:
                self._append_readme_log("AI调整失败", "ERROR")
                messagebox.showerror("错误", "AI调整失败，请检查修改需求或重试")
                
        except Exception as e:
            self._append_readme_log(f"AI调整时出错: {str(e)}", "ERROR")
            messagebox.showerror("错误", f"AI调整时出错: {str(e)}")
    
    def _clear_readme_editor(self):
        """清空README编辑器"""
        self.readme_editor.delete(1.0, tk.END)
        self.editor_status_var.set("编辑器已清空")
    
    def create_status_bar(self):
        """创建状态栏"""
        self.status_frame = ttk.Frame(self.root)
        self.status_frame.pack(fill=X, side=BOTTOM)
        
        # 状态标签
        self.status_var = tk.StringVar(value="就绪")
        self.status_label = ttk.Label(self.status_frame, textvariable=self.status_var)
        self.status_label.pack(side=LEFT, padx=5)
        
        # 分隔符
        ttk.Separator(self.status_frame, orient=VERTICAL).pack(side=LEFT, fill=Y, padx=5)
        
        # 连接状态
        self.connection_var = tk.StringVar(value="未连接")
        self.connection_label = ttk.Label(self.status_frame, textvariable=self.connection_var)
        self.connection_label.pack(side=LEFT, padx=5)
    
    def load_settings(self):
        """加载设置"""
        try:
            # 加载Gitee配置
            self.token_var.set(self.config_manager.get('gitee.access_token', ''))
            self.url_var.set(self.config_manager.get('gitee.base_url', 'https://gitee.com/api/v5'))
            self.branch_var.set(self.config_manager.get('gitee.default_branch', 'master'))
            
            # 加载AI配置
            self.deepseek_key_var.set(self.config_manager.get('ai.deepseek_api_key', ''))
            self.ai_timeout_var.set(self.config_manager.get('ai.timeout', '120'))
            
            # 加载README配置
            self.default_readme_mode_var.set(self.config_manager.get('readme.default_mode', 'AI智能生成'))
            self.default_template_var.set(self.config_manager.get('readme.default_template', '详细文档'))
            self.default_update_mode_var.set(self.config_manager.get('readme.default_update_mode', 'api'))
            
            # 加载批量操作配置
            self.prefix_var.set(self.config_manager.get('batch.prefix', ''))
            self.desc_var.set(self.config_manager.get('batch.description_template', '通过批量管理工具创建'))
            self.batch_concurrency_var.set(self.config_manager.get('batch.concurrency', '3'))
            self.batch_interval_var.set(self.config_manager.get('batch.interval', '1'))
            self.batch_timeout_var.set(self.config_manager.get('batch.timeout', '300'))
            
            # 加载仓库配置
            self.visibility_var.set(self.config_manager.get('repo.visibility', 'public'))
            self.private_var.set(self.config_manager.get('repo.private', False))
            self.issues_var.set(self.config_manager.get('repo.has_issues', True))
            self.wiki_var.set(self.config_manager.get('repo.has_wiki', True))
            self.auto_init_var.set(self.config_manager.get('repo.auto_init', True))
            self.readme_template_var.set(self.config_manager.get('repo.readme_template', '项目说明'))
            
            self.logger.info("设置加载完成")
            
        except Exception as e:
            self.logger.error(f"加载设置失败: {e}")
            messagebox.showerror("错误", f"加载设置失败: {str(e)}")
    
    def save_config(self):
        """保存配置"""
        try:
            # 验证Access Token
            token = self.token_var.get().strip()
            if token:
                is_valid, message = Validators.validate_access_token(token)
                if not is_valid:
                    messagebox.showerror("错误", f"Access Token验证失败: {message}")
                    return
            
            # 保存Gitee配置
            self.config_manager.set('gitee.access_token', token)
            self.config_manager.set('gitee.base_url', self.url_var.get().strip())
            self.config_manager.set('gitee.default_branch', self.branch_var.get().strip())
            
            # 保存AI配置
            deepseek_key = self.deepseek_key_var.get().strip()
            self.config_manager.set('ai.deepseek_api_key', deepseek_key)
            
            # 保存AI超时配置
            try:
                ai_timeout = int(self.ai_timeout_var.get().strip())
                self.config_manager.set('ai.timeout', str(ai_timeout))
            except ValueError:
                self.config_manager.set('ai.timeout', '120')
            
            # 保存README配置
            self.config_manager.set('readme.default_mode', self.default_readme_mode_var.get())
            self.config_manager.set('readme.default_template', self.default_template_var.get())
            self.config_manager.set('readme.default_update_mode', self.default_update_mode_var.get())
            
            # 保存批量操作配置
            self.config_manager.set('batch.prefix', self.prefix_var.get())
            self.config_manager.set('batch.description_template', self.desc_var.get())
            self.config_manager.set('batch.concurrency', self.batch_concurrency_var.get())
            self.config_manager.set('batch.interval', self.batch_interval_var.get())
            self.config_manager.set('batch.timeout', self.batch_timeout_var.get())
            
            # 保存仓库配置
            is_private = self.visibility_var.get() == "private"
            self.private_var.set(is_private)  # 更新兼容性变量
            
            self.config_manager.set('repo.visibility', self.visibility_var.get())
            self.config_manager.set('repo.private', is_private)
            self.config_manager.set('repo.has_issues', self.issues_var.get())
            self.config_manager.set('repo.has_wiki', self.wiki_var.get())
            self.config_manager.set('repo.auto_init', self.auto_init_var.get())
            self.config_manager.set('repo.readme_template', self.readme_template_var.get())
            
            # 保存到文件
            if self.config_manager.save_config():
                messagebox.showinfo("成功", "配置保存成功！")
                self.logger.info("配置保存成功")
                
                # 重新初始化API客户端
                if token:
                    self.gitee_api = GiteeAPI(token, self.url_var.get().strip())
                    self.gitee_manager = GiteeManager(token, self.url_var.get().strip())
                    # 更新仓库管理器的连接
                    if hasattr(self, 'repo_manager_widget'):
                        self.repo_manager_widget.set_gitee_manager(self.gitee_manager)
                    # 更新项目选择器的连接
                    if hasattr(self, 'project_selector'):
                        self.project_selector.set_gitee_api(self.gitee_api)
                
                # 更新DeepSeek AI配置
                deepseek_key = self.deepseek_key_var.get().strip()
                if deepseek_key:
                    from core.deepseek_ai import deepseek_ai
                    deepseek_ai.api_key = deepseek_key
                    deepseek_ai.use_local_analysis = False
                    self.logger.info("DeepSeek AI配置已更新")
                else:
                    from core.deepseek_ai import deepseek_ai
                    deepseek_ai.use_local_analysis = True
                    self.logger.info("DeepSeek AI配置为本地模式")
            else:
                messagebox.showerror("错误", "配置保存失败！")
                
        except Exception as e:
            self.logger.error(f"保存配置失败: {e}")
            messagebox.showerror("错误", f"保存配置失败: {str(e)}")
    
    def reset_config(self):
        """重置配置"""
        if messagebox.askyesno("确认", "确定要重置所有配置为默认值吗？"):
            try:
                # 重置为默认值
                self.token_var.set('')
                self.url_var.set('https://gitee.com/api/v5')
                self.branch_var.set('master')
                self.visibility_var.set('public')
                self.private_var.set(False)
                self.issues_var.set(True)
                self.wiki_var.set(True)
                self.auto_init_var.set(True)
                self.readme_template_var.set('项目说明')
                
                messagebox.showinfo("成功", "配置已重置为默认值")
                
            except Exception as e:
                messagebox.showerror("错误", f"重置配置失败: {str(e)}")
    
    def test_connection(self):
        """测试API连接"""
        token = self.token_var.get().strip()
        if not token:
            messagebox.showerror("错误", "请先输入Access Token")
            return
        
        # 验证token格式
        is_valid, message = Validators.validate_access_token(token)
        if not is_valid:
            messagebox.showerror("错误", f"Access Token格式错误: {message}")
            return
        
        try:
            # 禁用按钮
            self.test_btn.configure(state=DISABLED, text="测试中...")
            self.root.update()
            
            # 创建API客户端并测试
            api = GiteeAPI(token, self.url_var.get().strip())
            success, message = api.test_connection()
            
            if success:
                messagebox.showinfo("成功", message)
                self.connection_var.set("已连接")
                self.gitee_api = api
                self.gitee_manager = GiteeManager(token, self.url_var.get().strip())
                # 更新仓库管理器的连接
                if hasattr(self, 'repo_manager_widget'):
                    self.repo_manager_widget.set_gitee_manager(self.gitee_manager)
                
                # 同时更新DeepSeek AI配置
                deepseek_key = self.deepseek_key_var.get().strip()
                if deepseek_key:
                    from core.deepseek_ai import deepseek_ai
                    deepseek_ai.api_key = deepseek_key
                    deepseek_ai.use_local_analysis = False
                
                self.logger.info("API连接测试成功")
            else:
                messagebox.showerror("失败", f"连接测试失败: {message}")
                self.connection_var.set("连接失败")
                self.logger.error(f"API连接测试失败: {message}")
                
        except Exception as e:
            error_msg = f"连接测试异常: {str(e)}"
            messagebox.showerror("错误", error_msg)
            self.connection_var.set("连接异常")
            self.logger.error(error_msg)
        finally:
            # 恢复按钮
            self.test_btn.configure(state=NORMAL, text="测试连接")
    
    def on_project_added(self, project_data):
        """项目添加回调"""
        self.logger.info(f"添加项目: {project_data['name']} - {project_data['path']}")
        self.update_status(f"添加项目: {project_data['name']}")
    
    def on_project_removed(self, project_path):
        """项目删除回调"""
        self.logger.info(f"删除项目: {project_path}")
        self.update_status(f"删除项目")
    
    def start_batch_process(self):
        """开始批量处理"""
        # 检查是否有项目
        projects = self.project_selector.get_projects()
        if not projects:
            messagebox.showwarning("警告", "请先添加要处理的项目")
            return
        
        # 检查API连接
        if not self.gitee_api:
            messagebox.showerror("错误", "请先配置并测试Gitee API连接")
            return
        
        # 确认开始处理
        if not messagebox.askyesno("确认", f"确定要开始处理 {len(projects)} 个项目吗？"):
            return
        
        # 设置UI状态
        self.processing = True
        self.start_btn.configure(state=DISABLED)
        self.stop_btn.configure(state=NORMAL)
        self.progress_var.set(0)
        
        # 清空日志
        self.log_widget.clear_log()
        self.log_widget.append_log("开始批量处理项目...", "INFO")
        
        # 在新线程中处理
        self.process_thread = threading.Thread(target=self._batch_process_worker, args=(projects,))
        self.process_thread.daemon = True
        self.process_thread.start()
    
    def stop_batch_process(self):
        """停止批量处理"""
        if messagebox.askyesno("确认", "确定要停止当前的批量处理吗？"):
            self.processing = False
            self.log_widget.append_log("用户请求停止处理...", "WARNING")
    
    def _batch_process_worker(self, projects):
        """批量处理工作线程"""
        try:
            total_projects = len(projects)
            
            for i, project in enumerate(projects):
                if not self.processing:
                    self.log_widget.append_log("处理已停止", "WARNING")
                    break
                
                project_name = project['name']
                project_path = project['path']
                
                # 更新进度
                progress = (i / total_projects) * 100
                self.root.after(0, self.progress_var.set, progress)
                self.root.after(0, self.progress_percent_var.set, f"{int(progress)}%")
                self.root.after(0, self.update_status, f"处理项目 {i+1}/{total_projects}: {project_name}")
                
                # 更新项目状态
                self.root.after(0, self.project_selector.update_project_status, project_path, "处理中")
                
                # 处理单个项目
                success = self._process_single_project(project)
                
                if success:
                    self.root.after(0, self.project_selector.update_project_status, project_path, "完成")
                    self.root.after(0, self.log_widget.append_log, f"✓ 项目 '{project_name}' 处理完成", "SUCCESS")
                    # 成功后从项目列表中移除
                    self.root.after(0, self.project_selector.remove_project_by_path, project_path)
                else:
                    self.root.after(0, self.project_selector.update_project_status, project_path, "失败")
                    self.root.after(0, self.log_widget.append_log, f"✗ 项目 '{project_name}' 处理失败", "ERROR")
            
            # 完成处理
            self.root.after(0, self.progress_var.set, 100)
            self.root.after(0, self.progress_percent_var.set, "100%")
            self.root.after(0, self.log_widget.append_log, "批量处理完成", "SUCCESS")
            
        except Exception as e:
            error_msg = f"批量处理异常: {str(e)}"
            self.root.after(0, self.log_widget.append_log, error_msg, "ERROR")
            self.logger.error(error_msg)
        finally:
            # 恢复UI状态
            self.root.after(0, self._reset_ui_state)
    
    def _process_single_project(self, project) -> bool:
        """处理单个项目"""
        try:
            project_name = project['name']
            project_path = project['path']
            
            # 使用名称清理和翻译
            clean_name = name_translator.clean_name(project_name)
            if clean_name != project_name:
                self.root.after(0, self.log_widget.append_log, f"项目名称转换: {project_name} -> {clean_name}", "INFO")
            
            # 添加前缀
            prefix = self.prefix_var.get().strip()
            repo_name = f"{prefix}{clean_name}" if prefix else clean_name
            
            # 最终清理仓库名称（确保符合规范）
            repo_name = name_translator.clean_name(repo_name)
            
            self.root.after(0, self.log_widget.append_log, f"开始处理项目: {project_name}", "INFO")
            
            # 1. 验证仓库名称
            is_valid, message = Validators.validate_repo_name(repo_name)
            if not is_valid:
                self.root.after(0, self.log_widget.append_log, f"仓库名称验证失败: {message}", "ERROR")
                return False
            
            # 2. 创建本地README文件（如果启用自动初始化）
            if self.auto_init_var.get():
                # 检查README文件是否已存在
                if readme_generator.check_readme_exists(project_path):
                    self.root.after(0, self.log_widget.append_log, f"✓ README.md文件已存在，跳过生成", "INFO")
                else:
                    readme_info = {
                        'name': project_name,
                        'description': self.desc_var.get().replace('{project_name}', project_name),
                        'author': '开发者'
                    }
                    
                    template_type = self.readme_template_var.get()
                    self.root.after(0, self.log_widget.append_log, f"正在生成README文件 (模板: {template_type})...", "INFO")
                    
                    readme_created = readme_generator.create_readme_file(
                        project_path, 
                        template_type, 
                        readme_info
                    )
                    if readme_created:
                        if template_type == 'AI智能生成':
                            self.root.after(0, self.log_widget.append_log, f"✓ AI智能生成README.md文件完成", "SUCCESS")
                        else:
                            self.root.after(0, self.log_widget.append_log, f"✓ README.md文件已创建", "SUCCESS")
                    else:
                        self.root.after(0, self.log_widget.append_log, f"✗ README.md文件创建失败", "ERROR")
            
            # 3. 创建Gitee仓库
            is_private = self.visibility_var.get() == "private"
            repo_data = {
                'name': repo_name,
                'description': self.desc_var.get().replace('{project_name}', project_name),
                'private': is_private,
                'has_issues': self.issues_var.get(),
                'has_wiki': self.wiki_var.get(),
                'auto_init': False  # 我们本地创建README，所以设为False
            }
            
            visibility_text = "私有" if is_private else "公开"
            self.root.after(0, self.log_widget.append_log, f"创建{visibility_text}仓库: {repo_name}", "INFO")
            
            success, message, repo_info = self.gitee_api.create_repository(repo_data)
            if not success:
                # 检查是否是仓库名称冲突
                if "已存在" in message or "already" in message.lower():
                    # 尝试添加后缀重新创建
                    original_name = repo_name
                    for suffix in range(1, 10):  # 尝试添加1-9的后缀
                        new_repo_name = f"{original_name}_{suffix}"
                        
                        # 验证新名称
                        is_valid, validate_msg = Validators.validate_repo_name(new_repo_name)
                        if not is_valid:
                            continue
                        
                        # 尝试用新名称创建
                        repo_data['name'] = new_repo_name
                        self.root.after(0, self.log_widget.append_log, f"尝试使用新名称: {new_repo_name}", "INFO")
                        
                        success, message, repo_info = self.gitee_api.create_repository(repo_data)
                        if success:
                            repo_name = new_repo_name  # 更新成功的仓库名称
                            break
                    
                    if not success:
                        self.root.after(0, self.log_widget.append_log, f"创建仓库失败: {message}", "ERROR")
                        return False
                else:
                    self.root.after(0, self.log_widget.append_log, f"创建仓库失败: {message}", "ERROR")
                    return False
            
            self.root.after(0, self.log_widget.append_log, f"✓ 仓库创建成功: {repo_name}", "SUCCESS")
            
            # 4. 初始化本地Git仓库
            success, message = self.git_ops.init_repository(project_path)
            if not success:
                self.root.after(0, self.log_widget.append_log, f"Git初始化失败: {message}", "ERROR")
                return False
            
            # 5. 添加远程仓库
            if repo_info and 'ssh_url' in repo_info:
                remote_url = repo_info['ssh_url']
            else:
                # 获取用户名
                try:
                    user_response = self.gitee_api.session.get(
                        f'{self.gitee_api.base_url}/user',
                        params={'access_token': self.gitee_api.access_token}
                    )
                    username = user_response.json().get('login', 'unknown')
                    remote_url = f"git@gitee.com:{username}/{repo_name}.git"
                except:
                    remote_url = f"https://gitee.com/[username]/{repo_name}.git"
            success, message = self.git_ops.add_remote(project_path, 'origin', remote_url)
            if not success:
                self.root.after(0, self.log_widget.append_log, f"添加远程仓库失败: {message}", "ERROR")
                return False
            
            # 6. 提交所有文件
            success, message = self.git_ops.add_and_commit(project_path, "Initial commit")
            if not success and "没有需要提交的文件" not in message:
                self.root.after(0, self.log_widget.append_log, f"提交文件失败: {message}", "ERROR")
                return False
            
            # 7. 推送到远程仓库
            success, message = self.git_ops.push_to_remote(project_path, 'origin', self.branch_var.get())
            if not success:
                self.root.after(0, self.log_widget.append_log, f"推送失败: {message}", "ERROR")
                return False
            
            self.root.after(0, self.log_widget.append_log, f"✓ 推送成功", "SUCCESS")
            return True
            
        except Exception as e:
            error_msg = f"处理项目 '{project['name']}' 时发生异常: {str(e)}"
            self.root.after(0, self.log_widget.append_log, error_msg, "ERROR")
            self.logger.error(error_msg)
            return False
    
    def preview_repo_names(self):
        """预览仓库名称转换"""
        projects = self.project_selector.get_projects()
        if not projects:
            messagebox.showwarning("警告", "请先添加项目")
            return
        
        # 创建预览窗口
        preview_window = tk.Toplevel(self.root)
        preview_window.title("仓库名称预览")
        preview_window.geometry("800x500")
        preview_window.grab_set()
        
        # 主框架
        main_frame = ttk.Frame(preview_window, padding=10)
        main_frame.pack(fill=BOTH, expand=True)
        
        # 标题
        title_label = ttk.Label(main_frame, text="仓库名称转换预览", font=("等线", 14, "bold"))
        title_label.pack(pady=(0, 10))
        
        # 创建树视图
        columns = ('original', 'converted', 'readme', 'status')
        tree = ttk.Treeview(main_frame, columns=columns, show='headings', height=15)
        
        tree.heading('original', text='原始名称')
        tree.heading('converted', text='转换后名称')
        tree.heading('readme', text='README模板')
        tree.heading('status', text='验证状态')
        
        tree.column('original', width=200)
        tree.column('converted', width=200)
        tree.column('readme', width=120)
        tree.column('status', width=150)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(main_frame, orient=VERTICAL, command=tree.yview)
        tree.configure(yscrollcommand=scrollbar.set)
        
        # 填充数据
        prefix = self.prefix_var.get().strip()
        readme_template = self.readme_template_var.get()
        auto_init = self.auto_init_var.get()
        
        for project in projects:
            original_name = project['name']
            clean_name = name_translator.clean_name(original_name)
            repo_name = f"{prefix}{clean_name}" if prefix else clean_name
            repo_name = name_translator.clean_name(repo_name)
            
            # 验证名称
            is_valid, message = Validators.validate_repo_name(repo_name)
            status = "✓ 有效" if is_valid else f"✗ {message}"
            
            # README状态
            readme_status = readme_template if auto_init else "不生成"
            
            tree.insert('', END, values=(original_name, repo_name, readme_status, status))
        
        # 布局
        tree.pack(side=LEFT, fill=BOTH, expand=True)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        # 按钮框架
        button_frame = ttk.Frame(preview_window)
        button_frame.pack(fill=X, pady=10)
        
        ttk_bs.Button(
            button_frame,
            text="关闭",
            bootstyle=SECONDARY,
            command=preview_window.destroy,
            width=15
        ).pack(side=RIGHT, padx=5)
        
        # 居中显示
        preview_window.transient(self.root)
    
    def check_duplicate_names(self):
        """检查仓库名称是否重复"""
        projects = self.project_selector.get_projects()
        if not projects:
            messagebox.showwarning("警告", "请先添加项目")
            return
        
        if not self.gitee_api:
            messagebox.showerror("错误", "请先配置并测试Gitee API连接")
            return
        
        # 创建检查对话框
        check_window = tk.Toplevel(self.root)
        check_window.title("重名检查")
        check_window.geometry("600x400")
        check_window.grab_set()
        
        # 主框架
        main_frame = ttk.Frame(check_window, padding=10)
        main_frame.pack(fill=BOTH, expand=True)
        
        # 标题
        title_label = ttk.Label(main_frame, text="仓库名称重名检查", font=("等线", 14, "bold"))
        title_label.pack(pady=(0, 10))
        
        # 结果文本框
        result_text = tk.Text(main_frame, height=20, width=70)
        scrollbar_check = ttk.Scrollbar(main_frame, orient=VERTICAL, command=result_text.yview)
        result_text.configure(yscrollcommand=scrollbar_check.set)
        
        result_text.pack(side=LEFT, fill=BOTH, expand=True)
        scrollbar_check.pack(side=RIGHT, fill=Y)
        
        result_text.insert(END, "正在检查仓库名称...\n\n")
        check_window.update()
        
        # 检查重名
        prefix = self.prefix_var.get().strip()
        duplicate_count = 0
        
        try:
            # 获取用户的仓库列表
            success, user_repos, msg = self.gitee_api.get_user_repos(page=1, per_page=100)
            if not success:
                result_text.insert(END, f"无法获取仓库列表: {msg}\n")
                return
            
            existing_names = {repo['name'].lower() for repo in user_repos}
            
            for project in projects:
                original_name = project['name']
                clean_name = name_translator.clean_name(original_name)
                repo_name = f"{prefix}{clean_name}" if prefix else clean_name
                repo_name = name_translator.clean_name(repo_name)
                
                if repo_name.lower() in existing_names:
                    result_text.insert(END, f"❌ {original_name}\n")
                    result_text.insert(END, f"   转换名称: {repo_name}\n")
                    result_text.insert(END, f"   状态: 已存在同名仓库\n\n")
                    duplicate_count += 1
                else:
                    result_text.insert(END, f"✅ {original_name}\n")
                    result_text.insert(END, f"   转换名称: {repo_name}\n")
                    result_text.insert(END, f"   状态: 可以创建\n\n")
            
            result_text.insert(END, f"检查完成！\n")
            result_text.insert(END, f"重名项目: {duplicate_count} 个\n")
            result_text.insert(END, f"可创建项目: {len(projects) - duplicate_count} 个\n\n")
            result_text.insert(END, f"注意: 重名项目将自动添加数字后缀。\n")
            
        except Exception as e:
            result_text.insert(END, f"检查过程中出现错误: {str(e)}\n")
        
        # 关闭按钮
        ttk_bs.Button(
            check_window,
            text="关闭",
            bootstyle=SECONDARY,
            command=check_window.destroy,
            width=15
        ).pack(pady=5)
        
        check_window.transient(self.root)
    
    def auto_connect_api(self):
        """自动尝试连接API"""
        try:
            token = self.token_var.get().strip()
            if token:
                self.logger.info("检测到Access Token，自动尝试连接...")
                
                # 在后台线程中测试连接
                threading.Thread(target=self._auto_connect_worker, daemon=True).start()
            else:
                self.logger.info("未检测到Access Token，跳过自动连接")
                
        except Exception as e:
            self.logger.error(f"自动连接失败: {e}")
    
    def _auto_connect_worker(self):
        """自动连接工作线程"""
        try:
            token = self.token_var.get().strip()
            api = GiteeAPI(token, self.url_var.get().strip())
            success, message = api.test_connection()
            
            if success:
                self.root.after(0, self._on_auto_connect_success, api, message)
            else:
                self.root.after(0, self._on_auto_connect_failure, message)
                
        except Exception as e:
            error_msg = f"自动连接异常: {str(e)}"
            self.root.after(0, self._on_auto_connect_failure, error_msg)
    
    def _on_auto_connect_success(self, api, message):
        """自动连接成功回调"""
        self.connection_var.set("已连接")
        self.gitee_api = api
        self.gitee_manager = GiteeManager(self.token_var.get().strip(), self.url_var.get().strip())
        
        # 更新仓库管理器的连接
        if hasattr(self, 'repo_manager_widget'):
            self.repo_manager_widget.set_gitee_manager(self.gitee_manager)
        
        # 更新项目选择器的连接
        if hasattr(self, 'project_selector'):
            self.project_selector.set_gitee_api(self.gitee_api)
        
        # 更新DeepSeek AI配置
        deepseek_key = self.deepseek_key_var.get().strip()
        if deepseek_key:
            from core.deepseek_ai import deepseek_ai
            deepseek_ai.api_key = deepseek_key
            deepseek_ai.use_local_analysis = False
        
        self.logger.info(f"自动连接成功: {message}")
        
        # 显示连接成功的状态
        self.update_status("API连接成功")
    
    def _on_auto_connect_failure(self, error_message):
        """自动连接失败回调"""
        self.connection_var.set("连接失败")
        self.logger.warning(f"自动连接失败: {error_message}")
        self.update_status("请检查API配置")
    
    def create_repo_manager_tab(self):
        """创建仓库管理选项卡"""
        repo_frame = ttk.Frame(self.notebook)
        self.notebook.add(repo_frame, text="仓库管理")
        
        # 创建仓库管理器组件
        self.repo_manager_widget = RepoManagerWidget(repo_frame)
        self.repo_manager_widget.pack(fill=BOTH, expand=True)
        
        # 如果已经有Gitee管理器，设置连接
        if self.gitee_manager:
            self.repo_manager_widget.set_gitee_manager(self.gitee_manager)
    
    
    def _reset_ui_state(self):
        """重置UI状态"""
        self.processing = False
        self.start_btn.configure(state=NORMAL)
        self.stop_btn.configure(state=DISABLED)
        self.progress_var.set(0)
        self.progress_percent_var.set("0%")
        self.update_status("就绪")
    
    def update_status(self, message: str):
        """更新状态栏"""
        self.status_var.set(message)
        self.root.update()
    
    def on_closing(self):
        """关闭窗口事件处理"""
        if self.processing:
            if messagebox.askyesno("确认", "正在批量处理中，确定要退出吗？"):
                self.processing = False
                self.root.quit()
        else:
            self.root.quit()
    
    def run(self):
        """运行主窗口"""
        self.root.mainloop()


class RepoSelectorDialog:
    """仓库选择器对话框"""
    
    def __init__(self, parent, gitee_api):
        self.gitee_api = gitee_api
        self.selected_repo = None
        self.repo_data_map = {}  # 用于存储仓库数据的映射
        
        # 创建对话框
        self.dialog = ttk_bs.Toplevel(parent)
        self.dialog.title("选择仓库")
        self.dialog.geometry("800x600")
        self.dialog.resizable(True, True)
        
        # 居中显示
        self.dialog.transient(parent)
        self.dialog.grab_set()
        
        self.setup_ui()
        self.load_repositories()
    
    def setup_ui(self):
        """设置UI"""
        # 主框架
        main_frame = ttk.Frame(self.dialog)
        main_frame.pack(fill=BOTH, expand=True, padx=10, pady=10)
        
        # 标题
        title_label = ttk.Label(main_frame, text="选择要处理的仓库", font=("等线", 14, "bold"))
        title_label.pack(anchor=W, pady=(0, 10))
        
        # 仓库列表框架
        list_frame = ttk_bs.LabelFrame(main_frame, text="仓库列表", padding=10)
        list_frame.pack(fill=BOTH, expand=True, pady=(0, 10))
        
        # 创建Treeview
        columns = ('name', 'description', 'private', 'updated')
        self.tree = ttk.Treeview(list_frame, columns=columns, show='headings', height=15)
        
        # 设置列标题
        self.tree.heading('name', text='仓库名称')
        self.tree.heading('description', text='描述')
        self.tree.heading('private', text='类型')
        self.tree.heading('updated', text='更新时间')
        
        # 设置列宽
        self.tree.column('name', width=200)
        self.tree.column('description', width=300)
        self.tree.column('private', width=80)
        self.tree.column('updated', width=120)
        
        # 添加滚动条
        scrollbar = ttk.Scrollbar(list_frame, orient=VERTICAL, command=self.tree.yview)
        self.tree.configure(yscrollcommand=scrollbar.set)
        
        self.tree.pack(side=LEFT, fill=BOTH, expand=True)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        # 绑定双击事件
        self.tree.bind('<Double-1>', self.on_repo_double_click)
        
        # 按钮框架
        button_frame = ttk.Frame(main_frame)
        button_frame.pack(fill=X, pady=10)
        
        # 刷新按钮
        refresh_btn = ttk_bs.Button(
            button_frame,
            text="刷新列表",
            bootstyle=INFO,
            command=self.load_repositories,
            width=15
        )
        refresh_btn.pack(side=LEFT, padx=(0, 10))
        
        # 确定按钮
        ok_btn = ttk_bs.Button(
            button_frame,
            text="确定",
            bootstyle=SUCCESS,
            command=self.on_ok_clicked,
            width=15
        )
        ok_btn.pack(side=RIGHT, padx=(10, 0))
        
        # 取消按钮
        cancel_btn = ttk_bs.Button(
            button_frame,
            text="取消",
            bootstyle=SECONDARY,
            command=self.on_cancel_clicked,
            width=15
        )
        cancel_btn.pack(side=RIGHT)
    
    def load_repositories(self):
        """加载仓库列表"""
        try:
            # 清空现有列表和映射
            for item in self.tree.get_children():
                self.tree.delete(item)
            self.repo_data_map.clear()
            
            # 获取所有仓库列表
            success, repos, message = self.gitee_api.get_all_user_repos()
            
            if success:
                # 添加仓库到列表
                for repo in repos:
                    repo_type = "私有" if repo.get('private', False) else "公开"
                    updated_time = repo.get('updated_at', '')[:10] if repo.get('updated_at') else ''
                    description = repo.get('description', '')
                    if len(description) > 50:
                        description = description[:50] + '...'
                    
                    # 插入到Treeview
                    item_id = self.tree.insert('', 'end', values=(
                        repo.get('name', ''),
                        description,
                        repo_type,
                        updated_time
                    ))
                    
                    # 将仓库数据存储到映射中
                    self.repo_data_map[item_id] = repo
            else:
                messagebox.showerror("错误", "获取仓库列表失败")
                
        except Exception as e:
            messagebox.showerror("错误", f"加载仓库列表时出错: {str(e)}")
    
    def on_repo_double_click(self, event):
        """双击仓库项"""
        self.on_ok_clicked()
    
    def on_ok_clicked(self):
        """确定按钮点击"""
        selection = self.tree.selection()
        if not selection:
            messagebox.showwarning("警告", "请选择一个仓库")
            return
        
        # 获取选中的仓库信息
        selected_item = selection[0]
        
        if selected_item in self.repo_data_map:
            repo_data = self.repo_data_map[selected_item]
            if isinstance(repo_data, dict):
                self.selected_repo = repo_data
                self.dialog.destroy()
            else:
                messagebox.showerror("错误", f"仓库数据格式错误: {type(repo_data)}")
        else:
            messagebox.showerror("错误", "无法找到选中的仓库数据")
    
    def on_cancel_clicked(self):
        """取消按钮点击"""
        self.selected_repo = None
        self.dialog.destroy()
